package monte;

import monte.cs.CompetitionSystem;
import monte.exception.NoResultsException;

import java.util.ArrayList;
import java.util.LinkedList;

/**
 * 比赛进程类
 * <p>
 * 依据赛制和传入的队伍开始进行模拟
 */
public class MatchProcess {
    CompetitionSystem competitionSystem;
    ArrayList<Team> teams;

    LinkedList<Battle> battles;
    private LinkedList<BattleResult> battleResults;

    /**
     * 比赛进程类构造函数
     *
     * @param competitionSystem 比赛赛制对象
     * @param teams             传入的队伍数据
     */
    public MatchProcess(CompetitionSystem competitionSystem, ArrayList<Team> teams) {
        this.competitionSystem = competitionSystem.emptyObject();
        this.teams = teams;
        this.battles = new LinkedList<>();
    }

    /**
     * 开始模拟的主要函数
     */
    public void simulate() throws NoResultsException {
        try {
            battleResults = new LinkedList<>();
            competitionSystem.simulate(teams);
            battles = competitionSystem.getResults();
            for (Battle battle : battles) {
                battleResults.add(battle.getBattleResult());
            }
        } catch (NoResultsException e) {
            battleResults = null;
            throw e;
        }
    }

    /**
     * 取得一次比赛进程的模拟结果
     *
     * @return 比赛进程的模拟结果
     */
    public ProcessResult getResult() throws NoResultsException {
        if (battleResults == null) {
            throw new NoResultsException("没有比赛结果");
        }
        ArrayList<Integer> topTeams = competitionSystem.getTopTeams();
        double lossTop = calcLossTop(topTeams);
        double lossResult = calcLossResult();
        return new ProcessResult(lossTop, lossResult);
    }

    /**
     * 计算全比赛结果损失
     *
     * @return lossResult全比赛结果损失
     */
    private double calcLossResult() {
        double lossResults = 0;
        int count = 0;
        for (BattleResult battleResult : battleResults) {
            Team teamA = battleResult.getTeamA();
            Team teamB = battleResult.getTeamB();
            Team winner = battleResult.getWinner();
            if (teamA.getPower() > teamB.getPower() && winner != teamA) {
                lossResults++;
            }
            count++;
        }
        lossResults /= count;
        return lossResults;
    }

    /**
     * 计算前排队伍损失
     *
     * @param topTeams 前排队伍的序号列表
     * @return 返回lossTop
     */
    private double calcLossTop(ArrayList<Integer> topTeams) {
        double lossTop = 0;
        for (int i = 0; i < topTeams.size(); i++) {
            if (topTeams.get(i) != i) {
                lossTop++;
            }
        }
        lossTop /= topTeams.size();
        return lossTop;
    }

}
